package net.googlecode.demenkov.controllers;

import net.googlecode.demenkov.domains.Message;
import net.googlecode.demenkov.domains.Person;
import net.googlecode.demenkov.services.MessageService;
import net.googlecode.demenkov.services.PersonService;
import net.googlecode.demenkov.utils.MessageComporatorByDate;
import net.googlecode.demenkov.utils.PersonComparatorByName;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * Controller for actions with messages.
 *
 * @author Demenkov Yura
 */
@Controller
public class MessageController {
    @Autowired
    private PersonService personService;

    @Autowired
    private MessageService messageService;
    private int messagesPerPage = 5;

    /**
     * Gets authorizated person's email
     *
     * @return person's email
     */
    private String getUserEmail() {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        return ((UserDetails) principal).getUsername();
    }

    /**
     * Redirecting to send message form with list of groupmates and friends or person with id in request parameter "id"
     *
     * @param model with parameters for view-page
     * @return send message form
     */
    @RequestMapping(value = "/messages/sendmessage")
    public String viewSendMessageForm(HttpServletRequest request, Map model) {
        int personId = 0;
        if (request.getParameter("id") != null) {
            try {
                personId = Integer.valueOf(request.getParameter("id").toString());
            } catch (Exception e) {
                personId = 0;
            }
            Person person = personService.findPersonByEmail(getUserEmail());
            List<Person> persons = new ArrayList<Person>();
            Person toPerson = personService.getPerson(personId);
            if (toPerson != null) {
                persons.add(toPerson);
                model.put("message", new Message());
                model.put("toperson", persons);
                return "/sendmessage";
            }
        }
        Person person = personService.findPersonByEmail(getUserEmail());
        Set<Person> allPersons = new HashSet<Person>(person.getGroup().getPersons());
        allPersons.addAll(person.getAllFriends());
        List<Person> persons = new ArrayList<Person>(allPersons);
        Collections.sort(persons, new PersonComparatorByName());
        persons.remove(person);
        model.put("message", new Message());
        if (!persons.isEmpty()) {
            model.put("toperson", persons);
        } else {
            persons.add(person);
            model.put("toperson", persons);
        }
        return "/sendmessage";
    }

    /**
     * Sends message
     *
     * @param message to be sent
     * @param request with parameters for view-page
     * @return page with recieved messages
     */
    @RequestMapping(value = "/messages/sendnewmessage")
    public String sendNewMessage(@ModelAttribute("message") Message message, HttpServletRequest request) {
        Person person = personService.findPersonByEmail(getUserEmail());
        Person toPerson = personService.getPerson(Integer.valueOf(request.getParameter("to")));
        message.setFromPerson(person);
        message.setToPerson(toPerson);
        messageService.createMessage(message);
        List<Person> persons = new ArrayList<Person>(person.getGroup().getPersons());
        persons.remove(person);
        Collections.sort(persons, new PersonComparatorByName());
        return "redirect:/messages";
    }

    /**
     * Retirect to page with recieved messages. If attribute "type"=sent, than to page with sent messages
     *
     * @param request with parameters for view-page
     * @param model   with parameters for view-page
     * @return page with messages
     */
    @RequestMapping(value = "/messages")
    public String showMessages(HttpServletRequest request, Map model) {
        Person person = personService.findPersonByEmail(getUserEmail());
        List<Message> messages;
        int pageCount;
        if ((request.getParameter("type") != null) && (request.getParameter("type").equals("sent"))) {
            pageCount = person.getMessagesFrom().size() / messagesPerPage;
            if (person.getMessagesFrom().size() % messagesPerPage != 0) pageCount++;
            messages = new ArrayList<Message>(person.getMessagesFrom());
        } else {
            pageCount = person.getMessagesTo().size() / messagesPerPage;
            if (person.getMessagesTo().size() % messagesPerPage != 0) pageCount++;
            messages = new ArrayList<Message>(person.getMessagesTo());
        }
        Collections.sort(messages, new MessageComporatorByDate());
        int currentPage;
        if (request.getParameter("currentpage") == null) {
            currentPage = 1;
        } else {
            currentPage = Integer.valueOf(request.getParameter("currentpage").toString());
        }
        if (currentPage > pageCount) {
            currentPage = pageCount;
        }
        if (pageCount > 1) {
            if (messagesPerPage * currentPage <= messages.size()) {
                model.put("messages", messages.subList(messagesPerPage * (currentPage - 1), messagesPerPage * (currentPage)));
            } else {
                model.put("messages", messages.subList(messagesPerPage * (currentPage - 1), messages.size()));
            }
        } else {
            model.put("messages", messages);
        }
        request.setAttribute("unreadCount", person.getUnreadMessages().size());
        model.put("type", request.getParameter("type"));
        model.put("count", messages.size());
        model.put("pagecount", pageCount);
        model.put("currentpage", currentPage);
        return "/inmessages";
    }

    /**
     * Returns page numbre pageNumber in view-page with messages
     *
     * @param pageNumber of page
     * @param model      with parameters for view-page
     * @param request    with parameters for view-page
     * @return view-page with messages on pageNumber page
     */
    @RequestMapping(value = "messages/messagespage{pagenumber}")
    public String changeMessagePage(@PathVariable("pagenumber") int pageNumber, Map model, HttpServletRequest request) {
        model.put("currentpage", pageNumber);
        model.put("type", request.getParameter("type"));
        return "redirect:/messages";
    }

    /**
     * Redirect to view-message form with ability to response
     *
     * @param messageId of message
     * @param model     with parameters for view-page
     * @param request   with parameters for view-page
     * @return page with response form
     */
    @RequestMapping(value = "/messages/{messageid}")
    public String viewMessage(@PathVariable("messageid") int messageId, Map model, HttpServletRequest request) {
        Message message = messageService.getMessage(messageId);
        Person person = personService.findPersonByEmail(getUserEmail());
        if ((request.getParameter("type") == null) || (!request.getParameter("type").equals("sent")))
            if ((message != null) && (message.getToPerson().getPersonId() == person.getPersonId())) {
                model.put("recievedmessage", message);
                messageService.setReadMessage(message);
                Message newMessage = new Message();
                newMessage.setTitle(message.getTitle());
                newMessage.setToPerson(message.getFromPerson());
                model.put("message", newMessage);
                return "/message";
            } else {
                return "redirect:/messages";
            }
        else if (request.getParameter("type").equals("sent")) {
            if ((message != null) && (message.getFromPerson().getPersonId() == person.getPersonId())) {
                model.put("recievedmessage", message);
                Message newMessage = new Message();
                newMessage.setTitle(message.getTitle());
                newMessage.setToPerson(message.getToPerson());
                model.put("message", newMessage);
                model.put("type", "sent");
                return "/message";
            } else {
                return "redirect:/messages";
            }
        }
        return "redirect:/messages";
    }


    /**
     * Makes all unread messages of athorizated user read
     *
     * @return messages page
     */
    @RequestMapping(value = "/messages/readmessages")
    public String readAllMessages() {
        Person person = personService.findPersonByEmail(getUserEmail());
        for (Message message : person.getUnreadMessages()) {
            messageService.setReadMessage(message);
        }
        return "redirect:/messages";

    }

    /**
     * Deletes message with message id
     *
     * @param messageId of message
     * @param model     with parameters for view-page
     * @return messages page
     */
    @RequestMapping(value = "/messages/{messageId}/deletemessage")
    public String deleteMessage(@PathVariable("messageId") int messageId, Map model, HttpServletRequest request) {
        Message message = messageService.getMessage(messageId);
        Person person = personService.findPersonByEmail(getUserEmail());
        if ((person.getMessagesFrom().contains(message)) || (person.getMessagesTo().contains(message))) {
            messageService.deleteMessage(message);
            if (request.getParameter("type") != null) {
                model.put("type", request.getParameter("type"));
            }
            model.put("currentpage", request.getParameter("currentpage"));
            return "redirect:/messages";
        } else {
            if (request.getParameter("type") != null) {
                model.put("type", request.getParameter("type"));
            }
            model.put("currentpage", request.getParameter("currentpage"));
            return "redirect:/messages";
        }
    }

}
